﻿using System;
using System.Linq;
using System.Web.Mvc;
using Inscriptionem.Areas.Inscriptionem.Models.Enums;
using Inscriptionem.Areas.Inscriptionem.Models.Requests;
using Inscriptionem.Areas.Inscriptionem.Models.Views;
using Inscriptionem.Authorization;
using Inscriptionem.Controllers;
using Inscriptionem.Extensions;
using Inscriptionem.Services;

namespace Inscriptionem.Areas.Inscriptionem.Controllers
{
    [InscriptionemAuthorize(MemberRole.Admin, MemberRole.Moderator)]
    public class MemberController : Controller
    {
        private readonly ORM.DB DB;
        public MemberController()
        {
            DB = new ORM.DB();
        }

        public ActionResult Index()
        {
            return View("Index", new MemberCollectionViewModel());
        }

        public ActionResult Page(int ID)
        {
            if (ID <= 0)
            {
                return RedirectToAction("Index");
            }

            return View("Index", new MemberCollectionViewModel() {Page = ID});
        }

        public ActionResult Add()
        {
            return View("Add", new MemberViewModel() {IsRegistrationApproved = true, BirthDate = DateTime.Now});
        }

        [HttpPost]
        public ActionResult Add(MemberAddRequestModel model)
        {
            var result = new MemberViewModel();
            model.CopyTo(result);

            result.Error = ValidateMemberAddModel(model);

            if (result.Error == MemberError.None)
            {
                try
                {
                    if (LoginService.Register(model))
                    {
                        return Edit(new MemberRequestModel() {ID = DB.Members.First(m => m.Mail.ToLower() == model.Mail.ToLower()).ID});
                    }
                }
                catch(Exception)
                {
                    result.Error = MemberError.Other;
                }
            }

            return View("Add", result);
        }

        [HttpPost]
        public ActionResult Edit(MemberRequestModel model)
        {
            var result = new MemberViewModel();
            model.CopyTo(result);

            // Not the best way to check if "Edit" button was pressed
            if (result.ID > 0 && string.IsNullOrWhiteSpace(result.FirstName) && string.IsNullOrWhiteSpace(result.NickName) && string.IsNullOrWhiteSpace(result.LastName))
            {
                var member = DB.Members.FirstOrDefault(m => m.ID == result.ID);
                if (member == null)
                {
                    // Member not found
                    return RedirectToAction("Index");
                }

                result.FirstName = member.FirstName.Trim();
                result.NickName = member.NickName.Trim();
                result.LastName = member.LastName.Trim();
                result.BirthDate = member.BirthDate;
                result.Mail = member.Mail;
                result.IsReadOnly = member.IsReadOnly;
                result.IsRegistrationApproved = member.IsRegistrationApproved;

                // Roles will be automatically populated on View

                return View("Edit", result);
            }

            // Validate
            result.Error = ValidateMemberEditModel(model);
            if (result.Error == MemberError.None)
            {
                // Save changes
                try
                {
                    var member = DB.Members.FirstOrDefault(m => m.ID == result.ID);

                    if (member == null)
                    {
                        return RedirectToAction("Index");
                    }

                    member.FirstName = result.FirstName;
                    member.NickName = result.NickName;
                    member.LastName = result.LastName;
                    member.BirthDate = result.BirthDate;
                    member.IsReadOnly = result.IsReadOnly;
                    member.IsRegistrationApproved = result.IsRegistrationApproved;
                    member.ModifiedDate = DateTime.Now;

                    if (result.Roles != null)
                    {
                        var memberRoles = member.MemberRole;

                        foreach (var role in result.Roles)
                        {
                            var dbRole = DB.Roles.First(r => r.ID == role.ID);
                            var memberRole = memberRoles.FirstOrDefault(mr => mr.Role == dbRole);
                            if (memberRole == null && role.Enabled)
                            {
                                var newRole = new ORM.MemberRole()
                                                  {
                                                      Members = member,
                                                      Role = dbRole
                                                  };
                                DB.AddToMemberRoles(newRole);
                            }

                            if (memberRole != null && !role.Enabled)
                            {
                                DB.MemberRoles.DeleteObject(memberRole);
                            }
                        }
                    }

                    DB.SaveChanges();

                    return RedirectToAction("Index");
                }
                catch (Exception)
                {
                    result.Error = MemberError.Other;
                }
            }

            // Roles will be automatically populated on View

            return View("Edit", result);
        }

        [HttpPost]
        public ActionResult Search(string Text, int Page)
        {
            if (Page < 0)
            {
                Page = 0;
            }

            var result = new MemberSearchCollectionViewModel {Page = Page, Text = Text};

            return View("Search", result);
        }

        [HttpPost]
        public ActionResult Ban(int ID, int Page)
        {
            var member = DB.Members.FirstOrDefault(m => m.ID == ID);
            if (member != null)
            {
                member.IsReadOnly = true;
                member.ModifiedDate = DateTime.Now;
                DB.SaveChanges();
            }

            return View("Index", new MemberCollectionViewModel() { Page = Page });
        }

        #region Pagination
        public ActionResult Pagination(global::Inscriptionem.Models.Menu.Requests.PaginationRequestModel model)
        {
            return new MenuController().Pagination(model);
        }
        #endregion

        #region Implementation
        private MemberError ValidateMemberAddModel(MemberAddRequestModel Model)
        {
            var editResult = ValidateMemberEditModel(Model);
            if (editResult != MemberError.None)
            {
                return editResult;
            }

            if (DB.Members.Any(m => m.Mail.ToLower() == Model.Mail.ToLower()))
            {
                return MemberError.MailNotAvailable;
            }

            if (string.IsNullOrWhiteSpace(Model.Password))
            {
                return MemberError.PasswordEmpty;
            }

            if (string.IsNullOrWhiteSpace(Model.PasswordConfirmation) || Model.Password != Model.PasswordConfirmation)
            {
                return MemberError.PasswordNotMatch;
            }

            return MemberError.None;
        }

        private MemberError ValidateMemberEditModel(MemberRequestModel Model)
        {
            if (string.IsNullOrWhiteSpace(Model.FirstName))
            {
                return MemberError.FirstNameEmpty;
            }

            if (string.IsNullOrWhiteSpace(Model.LastName))
            {
                return MemberError.LastNameEmpty;
            }

            if (string.IsNullOrWhiteSpace(Model.Mail))
            {
                return MemberError.MailEmpty;
            }

            if (!Model.Mail.Contains("@"))
            {
                return MemberError.MailNotValid;
            }

            return MemberError.None;
        }
        #endregion
    }
}
